Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 <<   zurück
Visual Basic 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual Basic 2005

Visual Basic 2005
1.233 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-585-1
gp Kapitel 7 Weitere Möglichkeiten von Visual Basic 2005
  gp 7.1 Operatorüberladung
    gp 7.1.1 Die Syntax der Operatorüberladung
    gp 7.1.2 Beispiel einer Operatorüberladung
    gp 7.1.3 Überladung der Operatoren »True« und »False«
    gp 7.1.4 Benutzerdefinierte Konvertierungen
  gp 7.2 Collections (Auflistungen)
    gp 7.2.1 Die elementaren Schnittstellen der Auflistungsklassen
    gp 7.2.2 Die Schnittstelle »IList«
    gp 7.2.3 Die Klasse »ArrayList«
    gp 7.2.4 Das Sortieren der Elemente einer »ArrayList«
    gp 7.2.5 Die Schnittstelle »IDictionary«
    gp 7.2.6 Die Klasse »Hashtable«
    gp 7.2.7 Die Klassen »Queue« und »Stack«
    gp 7.2.8 Objektauflistungen im Überblick
    gp 7.2.9 Benutzerdefinierte Auflistungen
  gp 7.3 Generics
    gp 7.3.1 Ein paar allgemeine Worte
    gp 7.3.2 Die Typproblematik am Beispiel der Klasse »Stack«
    gp 7.3.3 Die Lösung mit einer generischen Klasse
    gp 7.3.4 Typparameter mit Constraints einschränken
    gp 7.3.5 Generische Methoden
    gp 7.3.6 Generics und Vererbung
    gp 7.3.7 Generische Klassen in der .NET-Klassenbibliothek
  gp 7.4 Fortgeschrittene Delegat-Techniken
    gp 7.4.1 Eine Beispielanwendung
    gp 7.4.2 Multicast-Delegaten
  gp 7.5 Attribute
    gp 7.5.1 Das »Flags«-Attribut
    gp 7.5.2 Anmerkungen zu den Attributen
    gp 7.5.3 Benutzerdefinierte Attribute

Kapitel 7 Weitere Möglichkeiten von Visual Basic 2005


Galileo Computing

7.1 Operatorüberladung  downtop

Visual Basic 2005 verfügt über eine Reihe Operatoren, die Sie für allgemeine Operationen einsetzen können. Werden zwei Zahlen dividiert, müssen Sie sich keine darüber Gedanken machen, welcher Code im Hintergrund vom Compiler erzeugt wird:


Dim ergebnis As Double = var1 / var2

Die Frage nach dem Typ der Operanden ist nicht bedeutungslos. Handelt es sich um ganzzahlige Typen, wird ein anderes Kompilat erzeugt als bei zwei Dezimalzahlen. Abhängig vom Typ der Operanden werden zwei unterschiedliche Operationen ausgeführt. Der Compiler entscheidet darüber, um welche Operation es sich dabei handelt, denn der »/«-Operator ist überladen.

Insbesondere für die elementaren Datentypen sind die meisten Operatoren überladen. Sie führen, je nach Typ der Operanden, unterschiedliche Operationen aus. Eine der großen Stärken von Visual Basic 2005 stellt .NET 2.0 dar, womit dem Entwickler das Instrumentarium gegeben wird, um im Bedarfsfall Operatoren benutzerdefiniert zu überladen.


Galileo Computing

7.1.1 Die Syntax der Operatorüberladung  downtop

Um Operatoren in einer Klasse oder einer Struktur zu überladen, stellt Visual Basic 2005 das Schlüsselwort Operator zur Verfügung, das nur in Verbindung mit Public Shared verwendet werden darf. Hinter dem Operator-Schlüsselwort wird der Operator angegeben, der überladen werden soll. Die folgende Syntax gilt für binäre Operatoren, die zwei Operanden für ihre Operation benötigen.


Public Shared Operator Operator (Operand1, Operand2) As Typ

Neben den binären gibt es auch unäre Operatoren, die nur einen Operanden verlangen. Stellvertretend seien hier die Operatoren »<« und »>« genannt. Für diese Operatorengruppe ändert sich die Syntax wie folgt:


Public Shared Operator Operator(Operand) As Typ

Abgeschlossen wird eine Operatorüberladung mit End Operator.

Wenn Sie eine Klasse um Methoden zur Operatorüberladung erweitern, sollten Sie folgende Punkte berücksichtigen:

1. Es können nur bereits vordefinierte Operatoren überladen werden. Sie können also keine neuen Operatoren »erfinden«.
       
2. Die Operationen von Operatoren auf den systemeigenen Typen können nicht umdefiniert werden.
       
3. Die Grundfunktionalität eines Operators bleibt immer erhalten: Ein binärer Operator benötigt immer zwei Operanden, ein unärer immer einen. Die Vorrangregeln können nicht beeinflusst werden.
       

In der folgenden Tabelle sind alle Operatoren aufgeführt, die in einer Klasse oder Struktur überladen werden dürfen.


Tabelle 7.1     Überladbare Operatoren

VB-Operator Bedeutung
+, –, Not, IsTrue, IsFalse Unäre Operatoren
+, –, *, /, \, &, ^, <<, >> Binäre Operatoren
=, <>, >, >=, <, <=, And, Like, Mod, Or, Xor Relationale Operatoren
CType Unäre Konvertierung

Einige Operatoren können nur paarweise überladen werden. Wollen Sie zum Beispiel den Vergleichsoperator »=« überladen, müssen Sie auch den Operator »<>« überladen. Damit erzwingt Visual Basic eine konsistente Prüfung auf Übereinstimmung und Nichtübereinstimmung.

Nicht alle Operatoren sind überladungsfähig. So können Sie den Zuweisungsoperator »=« nicht überladen, ebenso wenig AndAlso, OrElse und New. Für die beiden Operanden dürfen Sie nicht ByRef, Optional oder ParamArray angeben.


Galileo Computing

7.1.2 Beispiel einer Operatorüberladung  downtop

Wir wollen uns die Operatorüberladung jetzt an einem Beispiel ansehen. Dazu rufen wir uns die Methode IsBigger der Klasse GeometricObject in Erinnerung:


Public Shared Function IsBigger(ByVal obj1 As GeometricObject, _
ByVal obj2 As GeometricObject) As Boolean
If (obj1.GetFlaeche() >= obj1.GetFlaeche()) Then
Return True
End If
Return False
End Function

Mit


Dim kreis1 As Circle = New Circle(2)
Dim kreis2 As Circle = New Circle(3)
If GeometricObject.IsBigger(kreis1, kreis2) Then
...
End If

können wir zweifelsfrei prüfen, welcher der beiden Kreise der größere oder der kleinere ist. Selbstkritisch müssen wir aber auch feststellen, dass der Ausdruck


If kreis1 >= kreis2 Then

eher einer üblichen Vergleichsoperation entspricht. Bisher ist diese Vergleichsoperation jedoch nicht möglich, weil sie für Objekte vom Typ der Basisklasse GeometricObject oder in einer der abgeleiteten Klassen nicht definiert ist.

Um dieses Defizit auszugleichen, wollen wir jetzt den »>=«-Operator so überladen, dass er zur Laufzeit auf zwei Objekte vom Typ GeometricObject angewendet werden kann:


Public Shared Operator >=(ByVal geoObj1 As GeometricObject, _
ByVal geoObj2 As GeometricObject) As Boolean
If geoObj1.GetFlaeche() >= geoObj2.GetFlaeche() Then
Return True
End If
Return False
End Operator

Kompilieren wir die so ergänzte Klassendefinition, werden wir einen Compilerfehler erhalten, weil sich ein GeometricObject-Objekt jetzt nicht mehr eindeutig verhält. Wir werden gezwungen, einen weiteren Vergleichsoperator zu überladen, nämlich den, der die Umkehrung der vorher überladenen Vergleichsfunktion beschreibt.


Public Shared Operator <=(ByVal geoObj1 As GeometricObject, _
ByVal geoObj2 As GeometricObject) As Boolean
If geoObj1.GetFlaeche() <= geoObj2.GetFlaeche() Then
Return True
End If
Return False
End Operator

Nach dem anschließenden, jetzt erfolgreichen Kompilieren können wir mit


Dim kreis1 As Circle = New Circle(6)
Dim kreis2 As Circle = New Circle(3)
If (kreis1 >= kreis2) Then
' Anweisungen
End If

alternativ zu der von uns implementierten Methode IsBigger Vergleichsoperationen mit Objekten unserer Klasse ausführen.


Wird aus einer Klasse, die Operatoren überlädt, eine weitere Klasse abgeleitet, vererben sich die überladenen Operatoren an die abgeleitete Klasse.



Galileo Computing

7.1.3 Überladung der Operatoren »True« und »False«  downtop

Die booleschen Ausdrücke True und False werden durch die beiden Operatoren IsTrue und IsFalse abgebildet. Diese dienen dazu, Operationen wie beispielsweise


If myObject Then
...

zu ermöglichen. Diese Bedingungsprüfung ist sinnvoll, wenn der Rückgabewert direkt abhängig von einem Feld ist. Soll außerdem auch noch der Negationsoperator berücksichtigt werden, muss auch der »Not«-Operator überladen werden.


If Not myObject Then
...

Die Operatoren IsTrue und IsFalse gehören zu der Gruppe der Operatoren, die man nur paarweise überladen kann. Die Rückgabe ist ein boolescher Wert. Im folgenden Beispiel wird die Überladung aller drei Operatoren gezeigt. Dazu wird festgelegt, dass ein Objekt dann True zu bewerten ist, wenn der Inhalt des objektspezifischen ungleich der Zahl 0 ist.


' ----------------------------------------------------------
' Beispiel: ...\Kapitel 7\True_False_Operator
' ----------------------------------------------------------
Module Module1
Sub Main()
Dim myObject As New TestClass
myObject.IntValue = 0
If myObject Then
Console.WriteLine("Wert ist 0")
Else
Console.WriteLine("Wert ist ungleich 0")
End If
Console.ReadLine()
End Sub
End Module
Class TestClass
Public IntValue As Integer = 0
' Überladung des IsTrue-Operators
Public Shared Operator IsTrue(ByVal obj As TestClass) As Boolean
If (obj.IntValue <> 0) Then
Return False
End If
Return True
End Operator
' Überladung des IsFalse-Operators
Public Shared Operator IsFalse(ByVal obj As TestClass) As Boolean
If (obj.IntValue <> 0) Then
Return True
End If
Return False
End Operator
' Überladung des Not-Operators
Public Shared Operator Not(ByVal obj As TestClass) As Boolean
If (obj.IntValue <> 0) Then
Return True
End If
Return False
End Operator
End Class

Die dem Feld zugewiesene Zahl 8 wird


If (myObject) Then
...

zu der Anzeige


Wert ist ungleich 0

führen. Benutzen wir im Ausdruck den »Not«-Operator, kehrt sich die Logik natürlich um und führt zu der Ausgabe


Wert ist 0


Galileo Computing

7.1.4 Benutzerdefinierte Konvertierungen  toptop

Implizite benutzerdefinierte Konvertierung mit »Widening«

Stellen Sie sich vor, Sie hätten die Klasse ClassA folgendermaßen definiert:


Class ClassA
Public MyValue As Integer
Public Sub New(ByVal int As Integer)
MyValue = int
End Sub
End Class

Zugegeben, die Implementierung ist äußerst trivial, denn der Typ ClassA enthält nur ein Integer-Feld. Diese Definition könnte dazu verleiten, eine Referenz der Klasse ClassA einer Integer-Variablen wie folgt zuzuweisen:


Dim obj As New ClassA(34)
Dim x As Integer = obj

Selbstverständlich wird es nur bei einem Versuch bleiben, denn der Compiler stellt eine unzulässige Konvertierung des ClassA-Typs in einen Integer fest und macht das Unterfangen zunichte.

VB 2005 bietet uns jedoch die Möglichkeit, bestimmte Typkonvertierungen zu gestatten. Angenommen unser Ziel sei, das Codefragment tatsächlich einwandfrei zu kompilieren. Dazu müssen wir die Klasse um die Definition einer benutzerdefinierten Konvertierung wie folgt erweitern:


Class ClassA
Public MyValue As Integer
Public Sub New(ByVal int As Integer)
MyValue = int
End Sub
Public Shared Widening Operator CType(ByVal obj As ClassA) As Integer
Return obj.MyValue
End Operator
End Class

Sehen wir uns den Methodenkopf genauer an. Im Vergleich zu einer Methode, die einen Operator überlädt, ist die Definition der Methode zur Typkonvertierung um das neue Schlüsselwort Widening ergänzt. Den Schlüsselwörtern Widening Operator folgt der Operator CType, dessen Parameter ein Argument von dem Typ erwartet, der konvertiert werden soll. Der Rückgabetyp beschreibt den Zieldatentyp der benutzerdefinierten Konvertierung. In unserem Beispiel ist es Integer.

Die allgemeine Syntax der impliziten benutzerdefinierten Typkonvertierung lautet:


Public Shared Widening Operator CType(Eingabetyp) As Zieldatentyp

Die Aussage in unserem Beispiel ist also die folgende: Konvertiere ein Objekt vom Typ ClassA implizit in einen Integer.

Im Anweisungsblock der Konvertierungsmethode liefert das Return-Statement das Ergebnis der impliziten Konvertierung, denn um eine solche handelt es sich beim Einsatz des Modifikators Widening. In unserem Fall ist es der Inhalt des Feldes MyValue des Objekts, dessen Referenz die Methode im Parameter empfängt.

Weil ein Integer vom System implizit in einen Long-Typ konvertiert wird, wird jetzt auch das folgende Codefragment fehlerfrei kompiliert:


Dim a As ClassA = New ClassA(34)
Dim x As long x = a

Explizite benutzerdefinierte Konvertierung

Die explizite Typumwandlung ist unter Visual Basic 2005 nicht der Standard und muss mit dem Schalter


Option Strict On

ausdrücklich erzwungen werden. Nichtsdestotrotz sollten Sie dieser Art der Konvertierung Beachtung schenken und nicht vergessen, beim Testen des folgenden Beispiels den Schalter auch entsprechend einzustellen.

Eine implizite Konvertierung mit Widening bietet sich an, wenn bei einer Konvertierung keine Daten verloren gehen. Dahinter verbirgt sich eine Aufweitung des Typen. Explizite Konvertierungen sind dann einzusetzen, wenn bei der Konvertierung Daten verloren gehen oder verloren gehen könnten. Um das zu demonstrieren, nehmen wir nun an, die Klasse ClassA sei etwas anspruchsvoller:


Class ClassA
Public MyValue As Integer
Public MyText As String
Public Sub New(ByVal int As Integer, ByVal str As String)
MyValue = int
MyText = str
End Sub

Wir wollen die Referenz auf ein ClassA-Objekt in einen Integer konvertieren. Es kann uns nichts davon abhalten, weiterhin eine implizite benutzerdefinierte Konvertierung mit Widening anzubieten. Tatsache ist aber, dass uns bei der Typumwandlung Informationen verloren gehen, auch wenn diese vom empfangenden Element nicht benötigt werden – hier ist es das Feld vom Typ String. Legen Sie Wert auf eine stilistisch saubere Programmierung, sollten Sie deshalb eine explizite Konvertierung vorschreiben. Sie vermeiden dadurch außerdem, dass eine implizite Konvertierung automatisch ausgeführt wird, ohne dass der Aufrufer sie gewünscht hat.

Um eine benutzerdefinierte, explizite Typumwandlung zu implementieren, muss das Schlüsselwort Narrowing in der Methodensignatur angegeben werden. Die allgemeine Syntax ähnelt der impliziten benutzerdefinierten Konvertierung:


Public Shared Narrowing Operator CType(Eingabedatentyp) As Zieldatentyp

Sehen wir uns dazu das vollständige Beispiel an:


Class ClassA
Public MyValue As Integer
Public MyText As String
Public Sub New(ByVal int As Integer, ByVal str As String)
MyValue = int
MyText = str
End Sub
Public Shared Narrowing Operator CType(ByVal obj As ClassA) _
As Integer
Return obj.MyValue
End Operator
Public Shared Narrowing Operator CType(ByVal obj As ClassA) _
As String
Return obj.MyText
End Operator
End Class

ClassA beschreibt nun sogar zwei explizite Konvertierungen: in einen Integer und in einen String. Der Operator ist somit überladen. Programmcode, der ein ClassA-Objekt einem Integer zuweisen möchte, würde jetzt zu einer expliziten Konvertierung gezwungen, z.  B.:


Dim obj As ClassA = New ClassA(34, "Hallo Welt")
Dim x As Integer = CType(obj, Integer)

Vorausgesetzt natürlich, Option Strict ist auf On eingestellt. Analog lässt sich mit der Anweisung


Dim str As String = CType(obj, String)

eine Referenz vom Typ ClassA auch einer String-Variablen zuweisen, bei der die Zeichenfolgevariable den Inhalt des String-Feldes des Objekts erhält.

Implizite und explizite Konvertierung von Referenztypen

Im vorhergehenden Abschnitt war der Zieldatentyp ein einfacher Datentyp. Auf dieselbe Art und Weise kann auch in einen Referenztyp konvertiert werden. Nehmen wir an, es wären die beiden Klassen ClassA und ClassB wie folgt definiert:


' -------------- ClassA ----------------
Class ClassA
Public MyValue As Integer
Public ByBool As Boolean
End Class
' -------------- ClassB ----------------
Class ClassB
Public Value As Integer
Public LngValue As Long
End Class

Unser Ziel sei uns nun, die implizite Konvertierung eines ClassA-Objekts in ein ClassB-Objekt und umgekehrt zu erreichen, um beispielsweise den folgenden Code zu ermöglichen:


Module Module1
Sub Main()
Dim objA As New ClassA
objA.MyValue = 4711
Dim objB As ClassB = objA
Console.WriteLine("Value = {0}", objB.Value)
Console.ReadLine()
End Sub
End Module

Würden die beiden Klassen in einer Vererbungsbeziehung stehen und ClassA aus ClassB abgeleitet, wäre die Zuweisung kein Problem, da eine Subklassenreferenz implizit in eine Basisklassenreferenz konvertiert wird. Wie wir wissen, können wir auch die Referenz eines Basisklassenobjekts einer Subklassenreferenz zuweisen, müssen aber die Basisklassenreferenz dabei explizit konvertieren. Der passende Konvertierungsoperator wird uns aufgrund der Vererbungsbeziehung automatisch zur Verfügung gestellt. Die Ausgangssituation zwischen ClassA und ClassB ist in unserem Beispiel eine gänzlich andere und zwingt uns zu einer benutzerdefinierten Konvertierung, entweder implizit oder explizit.

Der Zieldatentyp ist nun ClassB, d. h., dass die Konvertierungsfunktion ein Objekt vom Typ ClassB als Rückgabewert liefert. In der Routine wird deshalb ein neues Objekt dieses Typs erzeugt. Man muss sich jetzt noch überlegen, welche gemeinsamen Merkmale beide Klassen aufweisen. In unserem Beispiel handelt es sich nur um das in beiden Klassen deklarierte Feld vom Typ Integer. Daher wird der Inhalt des Feldes MyValue des ClassA-Objekts dem Feld Value des ClassB-Objekts zugewiesen. Das so initialisierte Objekt wird als Ergebnis der impliziten Konvertierung bereitgestellt.


' Konvertierung eines ClassA- in ein ClassB-Objekt
Public Shared Widening Operator CType(ByVal obj As ClassA) _
As ClassB
Dim bObj As New ClassB
bObj.Value = obj.MyValue
Return bObj
End Operator

Die Konvertierung eines ClassA- in ein ClassB-Objekt hat Datenverlust zur Folge. Daher ist es besser, anstelle der impliziten eine explizite Konvertierung vorzuschreiben. Dazu muss nur das Schlüsselwort Widening gegen Narrowing ausgetauscht werden:


' Konvertierung eines ClassA- in ein ClassB-Objekt
Public Shared Narrowing Operator CType(ByVal obj As ClassA) _
As ClassB
Dim bObj As New ClassB
bObj.Value = obj.MyValue
Return bObj
End Operator

Nun wird die Typumwandlung nur über den Konvertierungsoperator erlaubt, führt aber ansonsten zum gleichen Ergebnis wie eine implizite Konvertierung:


Dim objA As New ClassA
objA.MyValue = 4711
Dim objB As ClassB = CType(objA, ClassB)

Auf der Buch-CD finden Sie die Beispielprogramme ConvertImplicitDemo und ConvertExplicitDemo, welche die implizite und explizite Konvertierung zeigen.

 <<   zurück
  
  Zum Katalog
Zum Katalog: Visual Basic 2005
Visual Basic 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Visual C# 2005






 Visual C# 2005


Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Das Programmierhandbuch SQL Server 2005






 Das Programmier-
 handbuch
 SQL Server 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de